const CellTemplate = require('./cell-template');
const Enums = require('../doc/enums');

/**
 * @property {WorksheetTemplate} sheet
 * @property {number} number
 * @property {CellTemplate[]} cells
 * @property {Object} style
 * @property {string} rowTag
 * @property {ColumnTemplate[]} cols
 */
class RowTemplate {
  constructor(sheet, number) {
    this.sheet = sheet;
    this.number = number;
    this.cells = [];
    this.style = null;
    // <row r="" ...>...</row>
    this.rowTag = '';
  }

  get cols() {
    return this.sheet.cols;
  }

  preRender(ctx) {
    let xml = `<row r="${this.number}"`;
    const styleId = ctx.styles.addStyleModel(this.style);

    if (this.height) {
      xml += ` ht="${this.height}" customHeight="1"`;
    }
    if (this.hidden) {
      xml += ' hidden="1"';
    }
    if (this.min > 0 && this.max > 0 && this.min <= this.max) {
      xml += ` spans="${this.min}:${this.max}"`;
    }
    if (styleId) {
      xml += ` s="${this.styleId}" customFormat="1"`;
    }

    xml += ' x14ac:dyDescent="0.25"';

    if (this.outlineLevel) {
      xml += ` outlineLevel="${this.outlineLevel}"`;
    }
    if (this.collapsed) {
      xml += ' collapsed="1"';
    }

    this.rowTag = xml + '>';
    this.cells.forEach(cell => cell.preRender(ctx));
    // cell.preRender结束再删除style
  }

  copy(row) {
    [
      'height',
      'hidden',
      'min',
      'max',
      'outlineLevel',
      'collapsed',
      'style'
    ].forEach(key => {
      this[key] = row[key];
    });
    if (this.number < this.sheet.start) {
      // 当前行不属于模板，需要复制值
      // row.values返回的数组从1开始，下标表示行号，需要向左偏移1
      this.values = row.values.slice(1);
    }
  }

  clear() {
    this.cells.forEach(cell => cell.clear());
    delete this.height;
    delete this.hidden;
    delete this.min;
    delete this.max;
    delete this.outlineLevel;
    delete this.collapsed;
    delete this.style;
    delete this.number;
  }

  render(ctx) {
    const { xmlStream, data } = ctx;
    const useIndexAsKey = Array.isArray(data);
    xmlStream.writeXml(this.rowTag);
    const { cells, sheet: { cols } } = this;
    const len = cells.length;

    for (let i = 0; i < len; i++) {
      const col = cols[i];
      const cell = cells[i];
      cell.value = data[useIndexAsKey ? col.number - 1 : col.key];
      cell.render(ctx);
    }

    xmlStream.writeXml('</row>');
  }

  addCell(type, count = 1) {
    let colNo = this.cells.length + 1;
    while (count--) {
      const col = this.sheet.getCol(colNo++);
      this.cells.push(CellTemplate.createCell(type, this, col));
    }
  }

  createCell(type, colNo) {
    let cell = this.cells[colNo - 1];
    if (!cell) {
      cell = this.cells[colNo - 1] = CellTemplate.createCell(type, this, this.sheet.getCol(colNo));
    } else if (cell.type !== type) {
      cell = this.cells[colNo - 1] = cell.to(type);
    }
    return cell;
  }

  getCell(colNo) {
    if (colNo > this.cells.length) {
      this.addCell(Enums.ValueType.Null, colNo - this.cells.length);
    }
    return this.cells[colNo - 1];
  }

  hasValue() {
    return this.cells.some(cell => cell.type !== Enums.ValueType.Null);
  }

  get lastCell() {
    return this.cells[this.cells.length - 1];
  }

  set values(val) {
    const { sheet } = this;
    sheet.staticRowValues.push(val);
    sheet.start = this.number + 1;
  }
}

module.exports = RowTemplate;
